package com.cloudkinto.service.mail.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cloudkinto.common.RabbitQueueConstant;
import com.cloudkinto.common.RedisKeyConstants;
import com.cloudkinto.common.common.DateUtils;
import com.cloudkinto.common.utils.EmojiConverterUtil;
import com.cloudkinto.common.utils.dict.StaticDict;
import com.cloudkinto.dao.*;
import com.cloudkinto.entity.*;
import com.cloudkinto.enumType.common.CountryEnum;
import com.cloudkinto.service.consumer.vo.mail.MailOneConsumerReq;
import com.cloudkinto.service.consumer.vo.mail.MailOrderConsumerReq;
import com.cloudkinto.service.consumer.vo.mail.MailSyncConsumerReq;
import com.cloudkinto.service.file.FileService;
import com.cloudkinto.service.mail.MailService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;
import com.cloudkinto.service.platform.PlatformOrderService;
import com.sun.mail.imap.IMAPStore;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.transaction.annotation.Transactional;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 *  service实现类
 * </p>
 * @author hua
 * @since 2025-01-10
 */
@Service
@Transactional(rollbackFor = Exception.class)//事务回滚
@RequiredArgsConstructor
public class MailServiceImpl extends ServiceImpl<MailDao, MailDo> implements MailService {
    private final MailDao dao;
    private final RedisTemplate redisTemplate;
    private final MailAccountDao mailAccountDao;
    private final RabbitTemplate rabbitTemplate;
    private final FileService fileService;
    @Value("${gbc.uploadPath.filePathTemp}")
    private String filePathTemp;
    @Autowired
    private final FileMoreDao fileMoreDao;
    private final PlatformOrderDao platformOrderDao;
    private final PlatformStoreDao platformStoreDao;
    private final PlatformOrderProductDao platformOrderProductDao;
    private final PlatformOrderService platformOrderService;

    @Override
    public int delete(Long id, Long userId) {
        MailDo entityDo = dao.selectById(id);
        handlerDeleteBefore(entityDo, userId);
        return dao.deleteById(id);
    }

    //做删除之前要执行的业务定制处理
    private void handlerDeleteBefore(MailDo entityDo, Long userId) {
        entityDo.setDeleteBy(userId);
        entityDo.setDeleteTime(new Date());
    }

    @Override
    public Object detail(Long id) {
        MailDo entityDo =  dao.selectById(id);
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return handlerDetailAfter(res);
    }

    //查询明细之后要执行的业务定制处理
    private Object handlerDetailAfter(Object res) {
        return res;
    }

    @Override
    public SingleResult pageInit() {
        return SingleResult.success("");
    }

    @Override
    public List<Object> getList(Map<String, String> map) {
        QueryWrapper<MailDo> wrapper = queryBuild(map);
        List<MailDo> list = this.list(wrapper);
        List<Object> result = handlerListAfter(list);
        return result;
    }

    @Override
    public PageResult getListPage(Map<String, String> map) {
        QueryWrapper<MailDo> wrapper = queryBuild(map);
        IPage<MailDo> page = pageInit(map);
        page = this.page(page, wrapper);
        List<Object> resList = handlerListAfter(page.getRecords());
        PageResult result = new PageResult(resList, (int)page.getCurrent(), (int)page.getSize(), (int)page.getTotal(), (int)page.getPages());
        return result;
    }

    //查询分页列表之后对列表数据的处理
    private List<Object> handlerListAfter(List<MailDo> list ){
        List<Object> result = new ArrayList<>();
        return result;
    }

    private IPage<MailDo> pageInit(Map<String, String> map) {
        IPage<MailDo> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }

    private QueryWrapper<MailDo> queryBuild(Map<String, String> map) {
        QueryWrapper<MailDo> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(map.get("keyword"))) {
            wrapper.like("keyword", map.get("keyword"));
        }
        return wrapper;
    }


    /**
     * 定时器 同步邮箱
     */
    @Override
    public void timingSynchronizationMail() {
        List<MailAccountDo> accountDoList = mailAccountDao.selectList(new LambdaQueryWrapper<MailAccountDo>()
                .eq(MailAccountDo::getStatus, "normal").isNotNull(MailAccountDo::getImap));
        for (MailAccountDo et : accountDoList) {
            MailSyncConsumerReq req = new MailSyncConsumerReq(et.getId(), true);
            rabbitTemplate.convertAndSend(RabbitQueueConstant.MailAccount_Sync, JSON.toJSONString(req));
        }
    }





    @Override
    public String syncMail(Long accountId, boolean autoFlag) {
        MailAccountDo mailAccountDo = mailAccountDao.selectById(accountId);
        if (mailAccountDo == null || StringUtils.isBlank(mailAccountDo.getPassword())) {
            return ("邮箱账号不存在，或无密钥");
        }

        if (autoFlag) {
            Double time = redisTemplate.opsForZSet().score(RedisKeyConstants.mailSyncTime, mailAccountDo.getId());
            long currency = System.currentTimeMillis();
            if (!(time == null || (currency - time) >= 60 * 2 * 1000)) {
                return "同步频率过快(2分钟同步一次)";
            }
            //无上次同步时间 或者 上次同步时间在10分钟之前
            redisTemplate.opsForZSet().add(RedisKeyConstants.mailSyncTime, mailAccountDo.getId(), currency - 60 * 1000);
        }
        this.syncByAccountId(mailAccountDo);
        return null;
    }


    public void syncByAccountId(MailAccountDo accountDo) {
        Store store = null;
        try {
            store = getIMAPStore(accountDo.getSmtp(), accountDo.getImap(), accountDo.getMailNo(), accountDo.getPassword());
            Folder[] fArr = store.getDefaultFolder().list();
            // 获得收件箱
            this.syncOneFolder(fArr, accountDo.getId(), accountDo.getMailNo(), accountDo.getSmtp(), accountDo.getStoreId(), accountDo.getCompanyId());
        } catch (Exception e) {
            if (e.toString().contains("javax.mail.AuthenticationFailedException")) {
                //账号密码不正确
                accountDo.setStatus("abnormal");
                mailAccountDao.updateById(accountDo);
                //通知 用户 邮箱授权过期
            }
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (store != null) {
                try {
                    store.close();
                } catch (MessagingException e) {
                    e.printStackTrace();
                }
            }
        }

    }


    public void syncOneFolder(Folder[] fArr, Long accountId, String mailNo, String smptHost, Long storeId, Long companyId) throws Exception {

        for (Folder folder : fArr) {
//            if (!StaticDict.Mail_Folder_Type.INBOX.getValue().equals(folder.getName())) { //只同步发件箱 测试时打开
//                continue;
//            }
            if (StaticDict.Mail_Folder_Type.Other.getValue().equals(folder.getFullName()) || StaticDict.Mail_Folder_Type.Other.getGmail().equals(folder.getFullName())
                    || StaticDict.Mail_Folder_Type.Other.getSina().equals(folder.getFullName())) {
                //其他文件他，即自定义文件夹
                syncOneFolder(folder.list(), accountId, mailNo, smptHost, storeId, companyId);
            }
            // 以读写模式打开收件箱
            if (StaticDict.Mail_Folder_Type.Other.getValue().equals(folder.getFullName()) || StaticDict.Mail_Folder_Type.Other.getGmail().equals(folder.getFullName())
                    || StaticDict.Mail_Folder_Type.Other.getSina().equals(folder.getFullName())) {
                continue;
            }
            System.out.println(mailNo + "::::" + folder.getName());
            folder.open(Folder.READ_ONLY);
            int total = folder.getMessageCount();
            // 得到收件箱文件夹信息，获取邮件列表
            String folderName = folder.getName();
            if (StaticDict.Mail_Type.NetEase.getSmtp().equals(smptHost)) {
                folderName = StaticDict.Mail_Folder_Type.getValueByEase(folderName);
            } else if (StaticDict.Mail_Type.Sina.getSmtp().equals(smptHost)) {
                folderName = StaticDict.Mail_Folder_Type.getValueBySina(folderName);
            } else if (StaticDict.Mail_Type.Outlook.getSmtp().equals(smptHost)) {
                folderName = StaticDict.Mail_Folder_Type.getValueByOutlook(folderName);
            } else if (StaticDict.Mail_Type.Gmail.getSmtp().equals(smptHost)) {
                //INBOX 已删除邮件 已加星标 重要 草稿 所有邮件 已发邮件
                folderName = StaticDict.Mail_Folder_Type.getValueByGmail(folderName);
            }
            if (StringUtils.isBlank(folderName)) {
                folderName = folder.getName();
            }
            if ("所有邮件".equals(folderName)) {
                continue;
            }

            Message[] msgArr = folder.getMessages();
            Collections.reverse(Arrays.asList(msgArr));
            //最近一封邮件的时间
            MailDo lastMail = dao.selectOne(new LambdaQueryWrapper<MailDo>()
                    .eq(MailDo::getAccountId, accountId)
                    .eq(MailDo::getFolderName, folderName)
                    .ne(MailDo::getType, StaticDict.Mail_Folder_Type.DRAFTS.getValue()).eq(MailDo::getStatus, "success")
                    .isNotNull(MailDo::getReceivedDate)
                    .last("order by received_date desc limit 1"));
            Date syncDate = lastMail == null ? DateUtils.passingDateHour(new Date(), -1) : new Date(lastMail.getReceivedDate().getTime() - 1000 * 60);
            List<Message> syncMessageList = new ArrayList<>();
            //查看是否有新邮件
            for (int i = 0; i < Math.min(total, 500); i++) {
                Message a = msgArr[i];
                try {
                    //最新11分钟 就同步
                    if ((a.getReceivedDate().getTime() >= syncDate.getTime()) ) {
                        syncMessageList.add(a);
                    } else {
                        break;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            // }
            //使得邮箱都是按照收件日期正序排序,方便后期sql查询
//            Collections.reverse(syncMessageList);
            for (int i = syncMessageList.size()-1; i >= 0; i--) {
                try {
                    syncOneMailMsg(syncMessageList.get(i), folderName, accountId, mailNo, storeId, companyId);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            Folder[] childFolder = folder.list();
            folder.close(false);
            if (childFolder.length > 0) {
                this.syncOneFolder(childFolder, accountId, mailNo, smptHost, storeId, companyId);
            }
        }
    }



    @Override
    public void syncOneMailMsg(Message a, String type, Long accountId, String mailNo, Long storeId, Long companyId) throws Exception {
        String folderName = type;//type区别收件发件 folderName区分属于哪个自定义文件夹
        boolean isRead = false;
        try {
            isRead = isNew(a);
        } catch (Exception e) {
            e.printStackTrace();
        }
        MimeMessage mimeMessage = (MimeMessage) a;
        String msgId = mimeMessage.getMessageID();
        String[] ids = a.getHeader("Message-Id");
        if (ids != null) {
            msgId = StringUtils.join(ids, ",");
        }
        MailDo et = dao.selectOne(new LambdaQueryWrapper<MailDo>().eq(MailDo::getMsgId, msgId).eq(MailDo::getAccountId, accountId).orderByDesc(MailDo::getId).last(" limit 1"));
        if (et != null) {
            return;
        }
//        String[] customIds = a.getHeader("custom_id");
//        String customId = StringUtils.join(customIds);
//        if (StringUtils.isNotBlank(customId)) {
//            et = dao.selectOne(new LambdaQueryWrapper<MailDo>().eq(MailDo::getCustomId, customId).eq(MailDo::getAccountId, accountId));
//        }
        StringBuilder plain = new StringBuilder();
        StringBuilder html = new StringBuilder();

        //获取邮箱正文
        this.getMailContent(a, plain, html);
        //收件人
//        String to = syncMailAddress(Message.RecipientType.TO, a);
        String cc = this.syncMailAddress(Message.RecipientType.CC, a);
//        String bcc = this.syncMailAddress(Message.RecipientType.BCC, a);

        MailDo mailDo = new MailDo();
        mailDo.setCompanyId(companyId);
        mailDo.setCc(cc);
        mailDo.setIsRead(isRead);
        String parsedPlain = EmojiConverterUtil.emojiConvert1(plain.toString());
        String parsedHtml = EmojiConverterUtil.emojiConvert1(html.toString());
        mailDo.setTextPlain(parsedPlain);
        mailDo.setTextHtml(parsedHtml);
        mailDo.setContentType(a.getContentType());
        InternetAddress[] addresses = (InternetAddress[]) mimeMessage.getReplyTo();
        StringBuilder relyTo = new StringBuilder();
        for (InternetAddress add : addresses) {
            if (relyTo.length() > 0) {
                relyTo.append(";");
            }
            String email = add.getAddress();
            if (email == null)
                email = "";
            else {
                email = MimeUtility.decodeText(email);
            }
            String personal = add.getPersonal();
            if (personal == null)
                personal = "";
            else {
                personal = MimeUtility.decodeText(personal);
            }
            String compositeto = personal + "<" + email + ">";
            relyTo.append(MimeUtility.decodeText(compositeto));
        }
        mailDo.setReplyTo(relyTo.toString());
        mailDo.setIsContainsFile(this.isContainAttach(a));

        mailDo.setMsgId(msgId);
        mailDo.setReceivedDate(a.getReceivedDate());
        mailDo.setSendDate(a.getSentDate());
        mailDo.setSubject(EmojiConverterUtil.emojiConvert1(a.getSubject() == null ? "" : a.getSubject()));
        mailDo.setAccountId(accountId);
        //发件人
        InternetAddress address = (InternetAddress) mimeMessage.getSender();
        String sender = "";
        String senderNick = "";
        Enumeration<Header> list = mimeMessage.getAllHeaders();
        while (list.hasMoreElements()) {
            Header header = list.nextElement();
            String name = header.getName();
            String value = header.getValue();
            if ("From".equals(name)) {
                sender = MimeUtility.decodeText(value.replace("\"", ""));
                if (sender.lastIndexOf(">") != -1) {
                    sender = sender.substring(0, sender.lastIndexOf(">"));
                    String[] senderAnd = sender.split("<");
                    sender = senderAnd[1];
                    senderNick = senderAnd[0];
                }
            } else if ("To".equals(name)) {
                String to = MimeUtility.decodeText(value.replace("\"", ""));
                mailDo.setMailTo(to.replaceAll(",", ";"));
            }
        }
        if (StringUtils.isBlank(sender)) {
            sender = MimeUtility.decodeText(address == null || address.getAddress() == null ? "" : address.getAddress());
            senderNick = MimeUtility.decodeText(address == null || address.getPersonal() == null ? "" : address.getPersonal());
        }
        mailDo.setSender(EmojiConverterUtil.emojiConvert1(sender));
        mailDo.setSenderNick(StringUtils.isBlank(senderNick) ? "" : EmojiConverterUtil.emojiConvert1(senderNick));
        if ("".equals(StaticDict.Mail_Folder_Type.getText(type))) {
            if (mailDo.getMailTo().contains(mailNo) && !mailDo.getSender().equals(mailNo)) {
                type = StaticDict.Mail_Folder_Type.INBOX.getValue();
            } else if (mailDo.getSender().equals(mailNo)) {
                type = StaticDict.Mail_Folder_Type.OUTBOX.getValue();
            } else {
                type = StaticDict.Mail_Folder_Type.INBOX.getValue();
            }
        }
        mailDo.setType(type);
        mailDo.setFolderName(folderName);
        dao.insert(mailDo);

        if (mailDo.getIsContainsFile()) {
//                List<Long> inLineFileList = new ArrayList<>();
//                List<Long> attachmentFileList = new ArrayList<>();
            List<Map> fileIdList = new ArrayList<>();
            saveAttachMent(a, mailDo.getId(), fileIdList);
            String htmlStr = html.toString();
            for (Map map : fileIdList) {
                Object fId = map.get("fileId");
                Object cid = map.get("Content-ID");
                if (fId == null || cid == null) {
                    continue;
                }
                Long fileId = Long.parseLong(fId.toString());
                String contentId = cid.toString();
                FileDo fileDo = fileService.getById(fileId);
                if (fileDo == null) {
                    continue;
                }
//                    String str = "<img src=\"cid:" + fileDo.getFileName().substring(0, fileDo.getFileName().lastIndexOf("."));
                String str = "src=\"cid:" + contentId;
                if (htmlStr.contains(str)) {
                    String newStr = "src=\"" + fileService.getFilePath(fileId);
                    htmlStr = StringUtils.replace(htmlStr, str, newStr);
                }
            }
            LambdaUpdateWrapper<MailDo> updateWrapper = new LambdaUpdateWrapper<MailDo>();
            updateWrapper.eq(MailDo::getId, mailDo.getId());
            updateWrapper.set(MailDo::getTextHtml, EmojiConverterUtil.emojiConvert1(htmlStr));
            this.update(updateWrapper);
        }
        //判断是不是Qoo10 订单
        if ("qoo10info@qoo10.jp".equals(mailDo.getSender()) &&  mailDo.getSubject().contains("注文番号：")) {
            MailOrderConsumerReq consumerReq = new MailOrderConsumerReq(mailDo.getSubject(), mailDo.getTextPlain(), storeId, mailDo.getCompanyId());
            rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformStore_MailOrder_Qoo10_Sync, JSON.toJSONString(consumerReq));
        }
    }

    /**
     * 邮件同步时，判断是不是订单邮件
     * @param req
     */
    @Override
    public void syncMailOrder(MailOrderConsumerReq req) {
        if (StringUtils.isBlank(req.getSubject()) || StringUtils.isBlank(req.getTextPlain()) || req.getCompanyId() == null) {
            return;
        }
        PlatformStoreDo storeDo = platformStoreDao.selectById(req.getStoreId());
        if (storeDo == null) {
            return;
        }
        //订单号
        String platformOrderNo = req.getSubject().substring(req.getSubject().indexOf("注文番号：") + "注文番号：".length(), req.getSubject().length() -1);
        if (StringUtils.isBlank(platformOrderNo)) {
            return;
        }
        PlatformOrderDo orderDo = platformOrderDao.selectOne(new LambdaQueryWrapper<PlatformOrderDo>()
                        .ge(PlatformOrderDo::getCreateTime, DateUtils.dateFormatToString(DateUtils.passingDate(new Date(), -7)))
                .eq(PlatformOrderDo::getCompanyId, req.getCompanyId()).eq(PlatformOrderDo::getPlatformOrderNo, platformOrderNo).last(" order by id desc limit 1"));
        if (orderDo != null) {
            return;
        }
        orderDo = new PlatformOrderDo();
        orderDo.setSource("mail");
        orderDo.setPlatformOrderNo(platformOrderNo);
        orderDo.setCompanyId(req.getCompanyId());
        orderDo.setTenantId(storeDo.getTenantId());
        orderDo.setPlatformCode(storeDo.getPlatformCode());
        orderDo.setStoreId(storeDo.getId());
        orderDo.setSite(storeDo.getSite());
        orderDo.setLastUpdateDate(new Date());
        orderDo.setStatus(StaticDict.Platform_Order_Status.Zero.getValue());
//        orderDo.setPlatformCode("qoo10");
        orderDo.setCountryRegionCode(CountryEnum.JP.getValue());

        List<PlatformOrderProductDo> productDos = new ArrayList<>();
        int remarkBegin = -1;
        int productBegin = -1;
        String[] split = req.getTextPlain().split("\r\n");
        if (req.getTextPlain().contains("■キャンセル内容") && req.getTextPlain().contains("キャンセル日時：")) {
            //取消了
            orderDo.setStatus(StaticDict.Platform_Order_Status.Four.getValue());
            orderDo.setCancelWay(0);
            for (String s : split) {
                if (s.startsWith("キャンセル日時：")) {//其实一个取消平台单号：344865081
                    String cancelDate = s.substring(s.indexOf("キャンセル日時：") + "キャンセル日時：".length());
                    try {
                        orderDo.setCancelTime(DateUtils.stringFormatToDate(cancelDate, "yyyy年MM月 HH時mm分ss秒"));
                    }catch (Exception e) {
                        log.error("qoo10邮件订单同步,"+platformOrderNo+",取消日期解析失败:" + s);
                    }
                }
                //todo sku 因不知道多个sku情况 所以不解析 以免异常
                //已下是单个sku情况
                //■キャンセル内容
                //------------------------------------------------------------
                //注文番号： 1017723485
                //商品番号(販売者商品コード)：1075194397(zhmrfd-1)
                //注文商品名：人気ビューティー商品 5点入超お得セット シートマスク 超お得セット シートマスク 大容量 30枚 7枚 ミニバッグ フェイスタオル 保湿 レチノール 乾燥対策
                //選択オプション名 : タイプ:Aタイプセット
                //オプションコード : zhmrfd-1a
                //商品価格：￥2100
                //キャンセル数量：1
                //------------------------------------------------------------
            }

        }
        else {
            for (int i = 0; i < split.length; i++) {
                String s = split[i];
                if (s.startsWith("[注文日時] ")) {
                    orderDo.setOrderTime(DateUtils.stringFormatToDate(s.substring("[注文日時] ".length()), "yyyy/MM/dd HH:mm:ss"));
                    orderDo.setPayTime(orderDo.getOrderTime());
                } else if (s.startsWith("[配送希望日] ")) {
                    String date = s.substring("[配送希望日] ".length());
                    if (StringUtils.isNotBlank(date)) {
                        //todo
                    }
                } else if (s.startsWith("[備考]")) {
                    remarkBegin = i;
                } else if (s.startsWith("[ご注文者]")) {
                    if (remarkBegin != -1) {
                        StringBuilder remark = new StringBuilder();
                        for (int j = remarkBegin + 1; j < i; j++) {
                            remark.append(split[j]);
                            remark.append("\r\n");
                        }
                        orderDo.setRemark(remark.toString());
                    }
                    if (split.length > i + 1) {
                        orderDo.setBuyerName(split[i + 1]);
                    }
                    if (split.length > i + 5 && split[i + 5].startsWith("  MAIL : ")) {
                        //郵箱
                        orderDo.setBuyerEmail(split[i + 5].substring("  MAIL : ".length()));
                    }
                } else if (s.startsWith("[お届け先]")) {
                    //收貨人信息
                    if (split.length > i + 1) {
                        orderDo.setReceiver(split[i + 1]);
                    }
                    if (split.length > i + 2) {
                        orderDo.setPostcode(split[i + 2].substring(1));
                    }
                    if (split.length > i + 3) {
                        //  神奈川県横浜市瀬谷区下瀬谷2-20-8 ベルーガ横浜502号室
                        String address = split[i + 3].trim();
                        if (address.contains("県")) {
                            String district = address.substring(0, address.indexOf("県") + 1);
                            orderDo.setDistrict(district);
                            address = address.substring(address.indexOf("県") + 1);
                        }
                        if (address.contains("市")) {
                            String cityCode = address.substring(0, address.indexOf("市") + 1);
                            orderDo.setCityCode(cityCode);
                            address = address.substring(address.indexOf("市") + 1);
                        }
                        orderDo.setAddressOne(address);
                        orderDo.setAddressTwo("");
                        orderDo.setProvinceCode("");
                    }
                    if (split.length > i + 4 && split[i + 4].startsWith("  TEL : ")) {
                        //电话
                        orderDo.setTelephone(split[i + 4].substring("  TEL : ".length()));
                    }
                } else if (s.startsWith("小計         : ")) {
                    String substring = s.substring("小計         : ".length(), s.indexOf("(円)"));
                    if (substring.matches("[0-9]+")) {
                        orderDo.setTotalAmount(BigDecimal.valueOf(Long.parseLong(substring)));
                    }
                    orderDo.setCurrencyCode(CountryEnum.JP.getCurrency());
                } else if (s.startsWith("[お買い上げ明細]")) {
                    //商品信息
                    productBegin = i;
                } else if (s.startsWith("************************************************")) {
                    if (productBegin == -1) {
                        continue;
                    }
                    for (int p = productBegin + 1; p < i; p++) {
                        if ("[商品]".equals(split[p])) {
                            PlatformOrderProductDo platItem = new PlatformOrderProductDo();
                            platItem.setPlatformOrderNo(platformOrderNo);
                            if (i > p + 1) {
                                String productName = split[p + 1];
                                platItem.setPlatformProductName(productName);
                                if (productName.contains("(") && productName.contains(")")) {
                                    String sku = productName.substring(productName.lastIndexOf("(") + 1, productName.lastIndexOf(")"));
                                    platItem.setPlatformSku(sku);
                                }
                            }
                            for (int z = productBegin + 2; z < i; z++) {
                                if ("[商品]".equals(split[z])) {
                                    break;
                                }
                                if (split[z].startsWith("価格")) {
                                    //価格 1279(円) x 1(個) = 1279(円)
                                    String itemAmount = split[z].substring(split[z].lastIndexOf("= ") + 2, split[z].lastIndexOf("(円)"));
                                    platItem.setItemAmount(BigDecimal.valueOf(Double.parseDouble(itemAmount)));
                                    String qty = split[z].substring(split[z].lastIndexOf("x ") + 2, split[z].lastIndexOf("(個)"));
                                    platItem.setPlatformQty(Integer.parseInt(qty));
                                }
                            }
                            platItem.setSkuType(1);
                            platItem.setCurrencyCode(CountryEnum.JP.getCurrency());
                            if (platItem.getPlatformQty() != null && StringUtils.isNotBlank(platItem.getPlatformSku())) {
                                productDos.add(platItem);
                            }
                        }
                    }
                }
            }
        }
        platformOrderDao.insert(orderDo);
        for (PlatformOrderProductDo productDo : productDos) {
            productDo.setOrderId(orderDo.getId());
        }
        if (!productDos.isEmpty()) {
            platformOrderService.matchSystemSku(productDos, storeDo.getId(), storeDo.getCompanyId(), storeDo.getTenantId());
            platformOrderProductDao.insertPlatformOrderItems(productDos);
        }
    }

    /**
     * 【保存附件】
     */
    public void saveAttachMent(Part part, Long mailId, List<Map> fileIdList) throws Exception {
        String fileName = "";
        if (part.isMimeType("multipart/*")) {
            Multipart mp = (Multipart) part.getContent();
            for (int i = 0; i < mp.getCount(); i++) {
                BodyPart mpart = mp.getBodyPart(i);
                String disposition = mpart.getDisposition();
                if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT)) || (disposition.equals(Part.INLINE)))) {
                    fileName = mpart.getFileName();
                    // if (StringUtils.isNotBlank(fileName) && (fileName.toLowerCase().contains("gb") || fileName.toLowerCase().contains("utf-8"))) {
                    if (StringUtils.isNotBlank(fileName)) {
                        fileName = MimeUtility.decodeText(fileName);
                    }
                    getFileId(fileName, mailId, fileIdList, mpart);
                } else if (mpart.isMimeType("multipart/*")) {
                    saveAttachMent(mpart, mailId, fileIdList);
                } else {
                    fileName = mpart.getFileName();
                    if ((fileName != null)) {
                        System.out.println("附件名称(未解码)：" + fileName);
                        fileName = MimeUtility.decodeText(fileName);
                    }
                    getFileId(fileName, mailId, fileIdList, mpart);

                }
            }
        } else if (part.isMimeType("message/rfc822")) {
            saveAttachMent((Part) part.getContent(), mailId, fileIdList);
        }
    }


    public void getFileId(String fileName, Long mailId, List<Map> fileIdList, BodyPart mpart) {
        if (StringUtils.isBlank(fileName)) {
            return;
        }
        Map map = new HashMap();
        try {
            Enumeration<Header> list = mpart.getAllHeaders();
            while (list.hasMoreElements()) {
                Header header = list.nextElement();
                String name = header.getName();
                String value = header.getValue();
                if ("Content-ID".equalsIgnoreCase(name)) {
                    map.put("Content-ID", value.substring(1, value.length() - 1));
                }
//            else if ("Content-Disposition".equals(name)){
//                map.put("type",value.startsWith("inline") ? "inline" : "attachment");
//            }
            }
        } catch (MessagingException e) {
            e.printStackTrace();
        }

        try {

            //方案一：先上传到临时文件夹，再上传到正式文件夹
//            Long fileId = fileService.uploadTempFile(fileName, mpart.getInputStream(), null);
//            addFileMoreDo(fileId, mailId);
//            fileService.uploadFile(fileId);
            //方案二 直接上传到正式路径
            Long fileId = fileService.uploadFileToFormalPath(mpart.getInputStream(), fileName);
            if (fileId == 0L) {
                return;
            }
            addFileMoreDo(fileId, mailId);

            map.put("fileId", fileId);
            fileIdList.add(map);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    public void addFileMoreDo(Long fileId, Long mailId) {
        if (fileId != null && fileId != 0L) {
            FileMoreDo fileMoreDo = new FileMoreDo();
            fileMoreDo.setFileId(fileId);
            fileMoreDo.setMailId(mailId);
            fileMoreDo.setType(StaticDict.File_Type.Mail.getValue());
            fileMoreDo.setCreateTime(new Date());
            fileMoreDao.insert(fileMoreDo);
        }
    }

    /**
     * 获取收件人，抄送人，密送人
     *
     * @param type
     * @return
     * @throws Exception
     */
    public String syncMailAddress(Message.RecipientType type, Message mimeMessage) throws Exception {
        String to = "";
        InternetAddress[] address = null;
        address = (InternetAddress[]) mimeMessage.getRecipients(type);
        if (address != null) {
            for (int i = 0; i < address.length; i++) {
                String email = address[i].getAddress();
                if (email == null)
                    email = "";
                else {
                    email = MimeUtility.decodeText(email.trim());
                }
                String personal = address[i].getPersonal();
                if (personal == null)
                    personal = email.split("@")[0];
                else {
                    personal = MimeUtility.decodeText(personal.replaceAll("\"", "").trim());
                }
                String compositeto = personal + "<" + email + ">";
                to += ";" + compositeto;
            }
            to = to.substring(1);
        }
        return to;
    }



    /**
     * 判断此邮件是否包含附件
     */
    public boolean isContainAttach(Part part) throws Exception {
        boolean attachFlag = false;
        if (part.isMimeType("multipart/*")) {
            Multipart mp = (Multipart) part.getContent();
            for (int i = 0; i < mp.getCount(); i++) {
                BodyPart mPart = mp.getBodyPart(i);
                String disposition = mPart.getDisposition();
                if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT)) || (disposition.equals(Part.INLINE))))
                    attachFlag = true;
                else if (mPart.isMimeType("multipart/*")) {
                    attachFlag = isContainAttach(mPart);
                } else {
                    String contype = mPart.getContentType();
                    if (contype.toLowerCase().contains("application"))
                        attachFlag = true;
                    if (contype.toLowerCase().contains("name"))
                        attachFlag = true;
                }
            }
        } else if (part.isMimeType("message/rfc822")) {
            attachFlag = isContainAttach((Part) part.getContent());
        }
        return attachFlag;
    }


    /**
     * 获取正文
     *
     * @param part
     * @param plain
     * @throws Exception
     */
    public void getMailContent(Part part, StringBuilder plain, StringBuilder html) throws Exception {
        String contentType = part.getContentType();
        int nameIndex = contentType.indexOf("name");
        boolean conName = false;
        if (nameIndex != -1)
            conName = true;
//        System.out.println("CONTENTTYPE: " + contentType);
        if (part.isMimeType("text/plain") && !conName) {
            plain.append((String) part.getContent());
        } else if (part.isMimeType("text/html") && !conName) {
            html.append((String) part.getContent());
        } else if (part.isMimeType("multipart/*")) {
            Multipart multipart = (Multipart) part.getContent();
            int counts = multipart.getCount();
            for (int i = 0; i < counts; i++) {
                getMailContent(multipart.getBodyPart(i), plain, html);
            }
        } else if (part.isMimeType("message/rfc822")) {
            getMailContent((Part) part.getContent(), plain, html);
        } else {
        }
    }


    /**
     * 【判断此邮件是否已读，如果未读返回返回false,反之返回true】
     */
    public boolean isNew(Message mimeMessage) throws MessagingException {
        boolean isNew = false;
        Flags flags = (mimeMessage).getFlags();
        Flags.Flag[] flag = flags.getSystemFlags();
//        System.out.println("flags's length: " + flag.length);
        for (int i = 0; i < flag.length; i++) {
            if (flag[i] == Flags.Flag.SEEN) {
                isNew = true;
//                System.out.println("seen Message.......");
                break;
            }
        }

        return isNew;
    }


    public Store getIMAPStore(String smtpHost, String imapHost, String mailNo, String password) throws Exception {
        if (StaticDict.Mail_Type.Outlook.getSmtp().equals(smtpHost)) {
//        String host = "outlook.office365.com";// change accordingly
            String mailStoreType = "imap";
            String popPort = "993";
            // 配置连接信息
            Properties properties = new Properties();
            properties.setProperty("mail.imap.partialfetch", "false");
            properties.setProperty("mail.imaps.partialfetch", "false");
            properties.put("mail.store.protocol", mailStoreType);
            properties.put("mail.imap.host", imapHost);
            properties.put("mail.imap.port", popPort);
            properties.put("mail.imap.starttls.enable", "true");
            Session emailSession = Session.getDefaultInstance(properties);
//            emailSession.setDebug(true);
            Store store = emailSession.getStore("imaps");
            store.connect(imapHost, mailNo, password);
            return store;
        } else if (StaticDict.Mail_Type.Gmail.getSmtp().equals(smtpHost)) {
            //https://www.google.com/settings/security/lesssecureapps   启用不够安全的应用的访问权限
            Properties props = System.getProperties();
            props.setProperty("mail.imap.partialfetch", "false");
            props.setProperty("mail.imaps.partialfetch", "false");
            props.setProperty("mail.store.protocol", "imaps");//设置电子邮件协议
            Session session = Session.getDefaultInstance(props, null);
            Store store = session.getStore("imaps");
            store.connect("imap.googlemail.com", mailNo, password);
            return store;
        } else {
            return this.getUStore(imapHost, mailNo, password);
        }
    }


    @Override
    public Properties getSmtpProperties(String smtp, String mailNo, String password, String port) {
        // 配置发送邮件的环境属性
        Properties props = new Properties();
        // 表示SMTP发送邮件，需要进行身份验证
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.host", smtp);
//        props.put("mail.smtp.port", ALIDM_SMTP_PORT); 需要开通25端口
        if (StaticDict.Mail_Type.Outlook.getSmtp().equals(smtp) || StaticDict.Rakuten_Mail_Account_Smtp.Smtp_Rakuten.getValue().equals(smtp)) {
            if (StringUtils.isBlank(port)) {
                port = "587";
            }
            //outlook
            props.put("mail.store.protocol", "smtp");
            props.put("mail.smtp.port", port);
            //开启SSL
            props.put("mail.smtp.starttls.enable", "true");
            props.put("mail.smtp.socketFactory.port", "587");
            props.put("mail.smtp.socketFactory.fallback", "false");
        } else {
            if (StringUtils.isBlank(port)) {
                port = "465";
            }
            // 如果使用ssl，则去掉使用25端口的配置，进行如下配置, 587 outlook
            props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
            props.put("mail.smtp.socketFactory.port", port);
            props.put("mail.smtp.port", "465");
        }

        // 发件人的账号，填写控制台配置的发信地址,比如xxx@xxx.com
        props.put("mail.user", mailNo);
        // 访问SMTP服务时需要提供的密码(在控制台选择发信地址进行设置)
        props.put("mail.password", password);
        // 构建授权信息，用于进行SMTP进行身份验证

        return props;
    }

    @Override
    public Authenticator getAuthenticator(Properties props) {
        Authenticator authenticator = new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                // 用户名、密码
                String userName = props.getProperty("mail.user");
                String password = props.getProperty("mail.password");
                return new PasswordAuthentication(userName, password);
            }
        };
        return authenticator;
    }


    /**
     * 此方法适配连接网易云以及qq
     *
     * @param imapHost
     * @param mailNo
     * @param password
     * @return
     * @throws Exception
     */
    public IMAPStore getUStore(String imapHost, String mailNo, String password) throws Exception {
        Properties props = System.getProperties();
        props.setProperty("mail.store.protocol", "imap");
        props.setProperty("mail.imap.host", imapHost);
        props.setProperty("mail.imap.port", "143");
        props.setProperty("mail.imap.partialfetch", "false");
        props.setProperty("mail.imaps.partialfetch", "false");
        HashMap<String, String> IAM = new HashMap<>();
        //带上IMAP ID信息，由key和value组成，例如name，version，vendor，support-email等。
        //解决 163邮箱不安全登录问题
        IAM.put("name", "myname");
        IAM.put("version", "1.0.0");
        IAM.put("vendor", "myclient");
        IAM.put("support-email", mailNo);
        Session session1 = Session.getInstance(props);
        IMAPStore store = (IMAPStore) session1.getStore("imap");
        store.connect(mailNo, password);//账号 //授权码
        store.id(IAM);
        return store;
    }
}
